package com.lzq.framework.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
 * @author 2019/3/19 13:56 by 刘赵强
 * 使用@Slfj注解的要求
 * <dependency>
 * <groupId>org.projectlombok</groupId>
 * <artifactId>lombok</artifactId>
 * </dependency>
 * <dependency>
 * <groupId>org.slf4j</groupId>
 * <artifactId>slf4j-api</artifactId>
 * </dependency>
 **/
@Slf4j
public class ExcelUtil {

    public static final String XLS = "xls";
    public static final String XLSX = "xlsx";

    final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private ExcelUtil() {
        log.error("不要自己创建对象");
    }

    public static void main(String[] args) {
        try {
            //7180
            //List<Row> rowList1 = getRowList();
            //System.out.println(rowList1.size());
            //550
            List<Row> rowList = testThread();

            System.out.println("集合长度="+rowList.size());
            rowList.sort(new Comparator<Row>() {
                @Override
                public int compare(Row o1, Row o2) {
                    return o1.getRowNum()-o2.getRowNum();
                }
            });
            for (Row row:rowList){
                System.out.println(row.getRowNum());
            }

            //System.out.println(670 % 10);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Workbook getWorkbook(File excel) {
        //.是特殊字符，需要转义！！！！！
        String[] split = excel.getName().split("\\.");
        Workbook wb = null;
        try {
            //根据文件后缀（xls/xlsx）进行判断
            if (XLS.equals(split[1])) {
                wb = new HSSFWorkbook(new FileInputStream(excel));
            } else if (XLSX.equals(split[1])) {
                wb = new XSSFWorkbook(excel);
            } else {
                log.error("文件类型错误");
                return null;
            }
        } catch (Exception e) {
            log.error("异常,errorMsg={}", e.getMessage(), e);
            return null;
        } finally {
            if (wb != null) {
                try {
                    wb.close();
                } catch (IOException e) {
                    log.error("workboo关闭异常", e);
                }
            }
        }
        return wb;
    }

    /**
     * 71399
     * 4849
     *
     * @throws Exception
     */
    public static List<Row> testThread() throws Exception {
        //excel文件路径
        String excelPath = "D:\\liuxc\\config\\cac-report\\finance\\2018\\08\\新存管还款明细表.xls";
        File excel = new File(excelPath);
        //判断文件是否存在
        if (!excel.isFile() || !excel.exists()) {
            System.err.println("找不到指定的文件");
            return Collections.emptyList();
        }

        Workbook wb = getWorkbook(excel);

        //开始解析 读取sheet 0
        Sheet sheet = wb.getSheetAt(0);
        //第一行是列名，所以不读
        int firstRowIndex = sheet.getFirstRowNum() + 1;
        int lastRowIndex = sheet.getLastRowNum();
        System.out.println("firstRowIndex: " + firstRowIndex);
        System.out.println("lastRowIndex: " + lastRowIndex);
        long startTime = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(15);
        Integer ThreadCount = lastRowIndex % 10 == 0 ? lastRowIndex / 10 : lastRowIndex / 10 + 1;
        CountDownLatch countDownLatch = new CountDownLatch(lastRowIndex);
        List<Row> rowList = new CopyOnWriteArrayList<>();
        BlockingQueue<Future<Row>> queue =  new ArrayBlockingQueue<>(1000);//需要给定一定的缓存长度
        for (Integer rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {
            Future<Row> submit = executorService.submit(new MyCallableProducer(countDownLatch, sheet.getRow(rIndex)));
            System.out.println("["+Thread.currentThread().getName()+"] queue 前 = "+queue.size());
            queue.add(submit);
            System.out.println(Thread.currentThread().getName()+"] queue 后 = "+queue.size());
            executorService.execute(new MyCallableConsumer(queue));
        }
        countDownLatch.await();
        executorService.shutdown();
        long endTime = System.currentTimeMillis();
        System.out.println("运行结束时间="+(endTime - startTime));
        return rowList;
    }


    // 文件读线程
    static class MyCallableProducer implements Callable<Row> {
        private CountDownLatch latch;
        private Row row;

        public MyCallableProducer(CountDownLatch latch,Row row) {
            this.latch = latch;
            this.row = row;
        }

        private void doWork() {
            //此方法可以添加一些业务逻辑，比如包装pojo等等操作，返回的值可以是任何类型
            Random rand = new Random();
            int time = rand.nextInt(10) * 1000;
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        @Override
        public Row call() throws Exception {

            System.out.println(Thread.currentThread().getName() + " 线程开始读取文件 ：" + row.getRowNum() + " ,时间为 " + sdf.format(new Date()));
            doWork();
            System.out.println(Thread.currentThread().getName() + " 线程读取文件 ：" + row.getRowNum() + " 完毕" + " ,时间为 " + sdf.format(new Date()));
            latch.countDown();
            return row;
        }
    }

    // 文件写线程
    static class MyCallableConsumer implements Runnable {
        private BlockingQueue<Future<Row>> queue;


        public MyCallableConsumer(BlockingQueue<Future<Row>> queue2) {
            this.queue = queue2;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName()+"消费前="+queue.size());
                Future<Row> future = queue.take();
                System.out.println(Thread.currentThread().getName()+"消费后="+queue.size());
                Row row = future.get();
                int firstCellIndex = row.getFirstCellNum();
                int lastCellIndex = row.getLastCellNum();
                for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {
                    Cell cell = row.getCell(cIndex);
                    if (cell != null) {
                        System.out.print(cell.toString() + "\t");
                        try {
                            TimeUnit.MILLISECONDS.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }


        }
    }


    /**
     * 71399
     *
     * @throws Exception
     */
    public static List<Row> getRowList() throws InterruptedException {
        //excel文件路径
        String excelPath = "D:\\liuxc\\config\\cac-report\\finance\\2018\\08\\新存管还款明细表.xls";
        File excel = new File(excelPath);
        //判断文件是否存在
        if (!excel.isFile() || !excel.exists()) {
            log.error("找不到指定的文件");
            return Collections.emptyList();
        }

        Workbook wb = getWorkbook(excel);

        //开始解析 读取sheet 0
        Sheet sheet = wb.getSheetAt(0);
        //第一行是列名，所以不读
        int firstRowIndex = sheet.getFirstRowNum() + 1;
        int lastRowIndex = sheet.getLastRowNum();
        System.out.println("firstRowIndex: " + firstRowIndex+"lastRowIndex: " + lastRowIndex);
        long startTime = System.currentTimeMillis();
        List<Row> rowList = new ArrayList<>();
        for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {
            rowList.add(sheet.getRow(rIndex));
            Thread.sleep(10);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("运行时间="+(endTime - startTime));
        return rowList;
    }




    public void aab(Row row){
        if (row != null) {
            int firstCellIndex = row.getFirstCellNum();
            int lastCellIndex = row.getLastCellNum();
            for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {
                Cell cell = row.getCell(cIndex);
                if (cell != null) {
                    System.out.print(cell.toString() + "\t");
                    try {
                        TimeUnit.MILLISECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            System.out.println();
        }
    }
}



